﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;

using eBook.Core;
using eBook.Core.BusinessObjects;
using eBook.Core.Contracts;

using Brotherhood.HttpUtilities;
using HtmlAgilityPack;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;


namespace eBook.Services
{
  public class OpenLibraryBookLookup : IBookLookup
  {
    // http://openlibrary.org/api/books?bibkeys=ISBN:0451526538&format=json&jscmd=data
    public boBookInfo GetBookInfoByISBN(ISBN isbn)
    {
      string url = string.Format("http://openlibrary.org/api/books?format=json&jscmd=data&bibkeys=ISBN:{0}", isbn.StrippedISBN);
      var result = HttpAutomation.DoGet(url, "");
      return this.ParseBookInfo(isbn, result.Response);
    }

    private boBookInfo ParseBookInfoXXX(ISBN isbn, string response)
    {
      boBookInfo info = new boBookInfo { InfoProvider = "OpenLib" };

      if ( string.IsNullOrEmpty(response) )
        return info;

      JObject jo = JObject.Parse(response);
      if ( jo == null )
        return info;
     
      List<string> links = new List<string>();
      List<string> bookauthors = new List<string>();
      List<string> topics = new List<string>();
      
      string joRoot = string.Format("ISBN:{0}", isbn.StrippedISBN);

      JArray publishers = ( JArray ) jo[joRoot]["publishers"];
      info.PublisherName = ( string ) publishers[0].SelectToken("name");

      JObject identifiers = ( JObject ) jo[joRoot]["identifiers"];
      if ( identifiers != null && identifiers["lccn"] != null)
        info.LCCN = ( string ) identifiers["lccn"][0];

      if ( identifiers != null && identifiers["isbn_10"] != null )
        info.ISBN10 = ( string ) identifiers["isbn_10"][0];
      

      JObject classifications = ( JObject ) jo[joRoot]["classifications"];
      if ( classifications != null && classifications["dewey_decimal_class"] != null )
        info.DeweyDecimal = ( string ) ( ( JArray ) classifications["dewey_decimal_class"] )[0];

      JObject cover = ( JObject ) jo[joRoot]["cover"];
      info.SmallImageURL  = (string) cover["small"];
      info.MediumImageURL = (string) cover["medium"];
      info.LargeImageURL  = (string) cover["large"];

      info.Title = (string) jo[joRoot]["title"];
      var numberOfPages = jo[joRoot]["number_of_pages"];
      if ( numberOfPages != null )
        info.NumberOfPages = jo[joRoot]["number_of_pages"].ToString();

      JArray authors = ( JArray ) jo[joRoot]["authors"];
      if ( authors != null )
      {
        foreach ( var x in authors )
          bookauthors.Add(( string ) x["name"]);
        info.Authors = bookauthors.ToArray();
      }

      JArray subjects = ( JArray ) jo[joRoot]["subjects"];
      if ( subjects != null )
      {
        foreach ( var x in subjects )
          topics.Add(( string ) x["name"]);
        info.Topics = topics.ToArray();
      }

      string olUrl = ( string ) jo[joRoot]["url"];
      links.Add(string.Format("OpenLibrary link|{0}", olUrl));
      
      if ( !string.IsNullOrEmpty(info.LCCN) )
        links.Add(string.Format("LC permalink|http://lccn.loc.gov/{0}", info.LCCN));

      if ( identifiers != null && identifiers["librarything"] != null )
      {
        string libraryThingId = ( string ) identifiers["librarything"][0];
        if ( !string.IsNullOrEmpty(libraryThingId) )
          links.Add(string.Format("LibraryThing link|http://www.librarything.com/work/{0}", libraryThingId));
      }

      
      if ( identifiers != null && identifiers["project_gutenberg"] != null )
      {
        string gutenberg = ( string ) identifiers["project_gutenberg"][0];
        links.Add(string.Format("Project Gutenberg link|http://www.gutenberg.org/ebooks/{0}", gutenberg));
      }

      info.Links = links.ToArray();

      return info;
    }


    private boBookInfo ParseBookInfo(ISBN isbn, string response)
    {
      boBookInfo info = new boBookInfo { InfoProvider = "OpenLib" };

      if ( string.IsNullOrEmpty(response) )
        return info;

      JObject jo = JObject.Parse(response);
      if ( jo == null )
        return info;

      if ( !jo.HasValues )
        return info;

      string joRoot = string.Format("ISBN:{0}", isbn.StrippedISBN);
      string joRootChildren = jo[joRoot].ToString();

      // root object does not comply to be a class name
      var settings = new JsonSerializerSettings();
      settings.TypeNameHandling = TypeNameHandling.All;
      settings.MaxDepth = 5;
      var t = JsonConvert.DeserializeObject<OpenLibraryResponse>(joRootChildren, settings);

      if ( t == null )
        return info;

      List<string> links = new List<string>();

      if ( t.publishers != null )
      {
        var p = t.publishers.FirstOrDefault();
        info.PublisherName = p != null ? p.name : string.Empty;
      }
      info.PublicationDate = t.publish_date;

      if ( t.identifiers != null )
      {
        info.LCCN   = t.identifiers.lcnn != null ? t.identifiers.lcnn[0] : string.Empty;
        info.ISBN10 = t.identifiers.isbn_10 != null ? t.identifiers.isbn_10[0] : string.Empty;
        info.ISBN13 = t.identifiers.isbn_13 != null ? t.identifiers.isbn_13[0] : string.Empty;

        if ( t.identifiers.librarything != null )
        {
          var libraryThingId = t.identifiers.librarything.FirstOrDefault();
          if ( !string.IsNullOrEmpty(libraryThingId) )
            links.Add(string.Format("LibraryThing link|http://www.librarything.com/work/{0}", libraryThingId));
        }

        if ( t.identifiers.project_gutenberg != null )
        {
          var pgId = t.identifiers.project_gutenberg.FirstOrDefault();
          if ( !string.IsNullOrEmpty(pgId) )
            links.Add(string.Format("Project Gutenberg link|http://www.gutenberg.org/ebooks/{0}", pgId));
        }
      }

      if ( t.classifications != null )
      {
        if ( t.classifications.dewey_decimal_class != null )
          info.DeweyDecimal = t.classifications.dewey_decimal_class.FirstOrDefault();
      }

      if ( t.cover != null )
      {
        info.SmallImageURL = t.cover.small;
        info.MediumImageURL = t.cover.medium;
        info.LargeImageURL = t.cover.large;
      }

      info.Title = t.title;
      info.Subtitle = t.subtitle;

      info.NumberOfPages = t.number_of_pages == 0 ? string.Empty : t.number_of_pages.ToString();
      if ( t.authors != null )
        info.Authors = t.authors.Select(x => x.name).ToArray();

      if ( t.subjects != null )
        info.Topics = t.subjects.Select(x => x.name).ToArray();

      if ( !string.IsNullOrEmpty(t.url) )
        links.Add(string.Format("OpenLibrary link|{0}", t.url));

      if ( !string.IsNullOrEmpty(info.LCCN) )
        links.Add(string.Format("LC permalink|http://lccn.loc.gov/{0}", info.LCCN));

      info.Links = links.ToArray();

      return info;
    }





  }



}

